package com.base.utils;

import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

import java.math.BigDecimal;
import java.util.List;

import static java.lang.Math.PI;

/**
 *  @Date: 2020/5/12 14:29
 *  @Description:
 *  计算坐标之间的距离，工具类，改善接口速度
 */ 
public class CaculateDistanceTest {
    public static void main(String[] args) {
        GlobalCoordinates source = new GlobalCoordinates(29.490295, 106.486654);
        GlobalCoordinates target = new GlobalCoordinates(29.615467, 106.581515);

        double meter1 = getDistanceMeter(source, target, Ellipsoid.Sphere);
        double meter2 = getDistanceMeter(source, target, Ellipsoid.WGS84);

        System.out.println("Sphere坐标系计算结果：" + meter1 + "米");
        System.out.println("WGS84坐标系计算结果：" + meter2 + "米");
    }

    public static double getDistance(Double lat1, Double lon1, Double lat2, Double lon2) {
        GlobalCoordinates source = new GlobalCoordinates(lat1, lon1);
        GlobalCoordinates target = new GlobalCoordinates(lat2, lon2);
        double meter1 = getDistanceMeter(source, target, Ellipsoid.Sphere);
        if (meter1 < 0) {
            meter1 = -1 * meter1;
        }
        return meter1;
    }

    public static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid) {
        //创建GeodeticCalculator，调用计算方法，传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);

        return geoCurve.getEllipsoidalDistance();
    }

    /**
     * 查找附近的门店
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @param distince  距离 (千米)
     * @return List 符合距离范围的所有的点
     * @Data 2018.10.26
     */
    public  static  String[] findNearbyStore(BigDecimal longitude, BigDecimal latitude, Integer distince) {
        BigDecimal lon= longitude.setScale(4,BigDecimal.ROUND_HALF_UP);
        BigDecimal lat= latitude.setScale(4, BigDecimal.ROUND_HALF_UP);

//        String[] split = getNearbyByLongitudeAndLatitudeAndDistince(lon, lat, distince).split("-");

        return getAround(lat.doubleValue(),lon.doubleValue() , distince);
    }


    /**
     * @param longitude 经度
     * @param latitude  纬度
     * @param distince  距离（千米）
     * @return String 格式：经度最小值-经度最大值-纬度最小值-纬度最大值
     * @Description 计算给定经纬度附近相应公里数的经纬度范围
     * @Data 2018.10.26
     **/
    public static String getNearbyByLongitudeAndLatitudeAndDistince(BigDecimal longitude, BigDecimal latitude, Integer distince) {
        double r = 6371.393;    // 地球半径千米
        double lng = longitude.doubleValue();
        double lat = latitude.doubleValue();
        double dlng = 2 * Math.asin(Math.sin(distince / (2 * r)) / Math.cos(lat * PI / 180));
        dlng = dlng * 180 / PI;// 角度转为弧度
        double dlat = distince / r;
        dlat = dlat * 180 / PI;
        double minlat = lat - dlat;
        double maxlat = lat + dlat;
        double minlng = lng - dlng;
        double maxlng = lng + dlng;

        return minlng + "-" + maxlng + "-" + minlat + "-" + maxlat;
    }

    /**
     * 根据经纬度和半径计算经纬度范围
     *
     * @param raidus 单位米
     * @return minLat, minLng, maxLat, maxLng
     */
    public static String[] getAround(double lat, double lon, int raidus) {

        Double latitude = lat;
        Double longitude = lon;

        Double degree = (24901 * 1609) / 360.0;
        double raidusMile = raidus;

        Double dpmLat = 1 / degree;
        Double radiusLat = dpmLat * raidusMile;
        Double minLat = latitude - radiusLat;
        Double maxLat = latitude + radiusLat;

        Double mpdLng = degree * Math.cos(latitude * (PI / 180));
        Double dpmLng = 1 / mpdLng;
        Double radiusLng = dpmLng * raidusMile;
        Double minLng = longitude - radiusLng;
        Double maxLng = longitude + radiusLng;
        return new String[]{minLat.toString(), minLng.toString(), maxLat.toString(), maxLng.toString()};
    }
}